<template>
  <!-- 表单 -->
  <linkage-form
    :form-items="renderParamsList"
    :conditions="config.condition || []"
    :form-data="config.value"
    :node-setting="false"
    :layout-col-num="+(config.columnNum || 1)"
    class="operator-configuration"
    @change="formItemValueChange"
  />
</template>

<script lang="ts">
import Big from 'big.js'
import LinkageForm from '@/components/studio/data/set-params/linkage-form/LinkageForm.vue'
import { Vue, Component, Prop } from 'vue-property-decorator'
import { isNumber, cloneDeep } from 'lodash'

interface IParamItem {
  name: string
  value: any
  type: string
  default: any
  chineseName: string
  message: string
  label: string
  rules: any[]
  step?: number
  basis?: number
  stepCount?: number
  options?: Array<{ value: string; label: string }>
  status: 'normal' | 'disable' | 'hide'
  newFeatures?: any[]
  props: any
}

interface IConfig {
  params: IParamItem[]
  value: any
  condition?: any[]
  columnNum?: number
}

@Component({
  components: {
    LinkageForm,
  },
})
export default class OperatorConfiguration extends Vue {
  @Prop() config!: IConfig
  @Prop({ default: false }) disabled!: boolean

  private commonFormProps = {
    disabled: this.disabled,
    size: 'small',
  }

  private numberTypeSet = new Set([
    'number',
    'int',
    'inputNumber',
    'sliderWithInput',
  ]) // 数值类型参数

  private get renderParamsList() {
    const { params } = this.config
    const list = cloneDeep(params)
      .filter((item) => item.status !== 'hide')
      .map((item) => {
        if (['inputNumber', 'sliderWithInput'].includes(item.type)) {
          item.type = 'sliderWithInput'
          item.props = {
            ...item.props,
            ...this.extraFormProps(item),
          }
        }
        return {
          ...item,
          disabled: item.status === 'disable',
        }
      })
    return list
  }

  public formItemValueChange(value: any, key: string) {
    this.$set(this.config.value, key, value)
  }

  /**
   * 根据不同的类型组装的一些特殊配置
   */
  private extraFormProps(item: IParamItem) {
    if (this.numberTypeSet.has(item.type)) {
      const {
        props: { min, max },
      } = item // 配置中的最小最大限制
      // 设置了基数情况下直接取基数
      const value = isNumber(item.basis)
        ? item.basis
        : item.default || item.value || 1
      const bigValue = new Big(value) // 以默认值为基准，按 基准 * 调整比例为 步长
      const stepValue = (value === 0 ? new Big(1) : bigValue)
        .times(item.step || 100)
        .div(100) // 步长
      const stepCount = Math.ceil((item.stepCount || 100) / 2) // 总步数
      const intervalValue = stepValue.times(stepCount) // 左/右间隔值
      const calcMaxValue = +bigValue.plus(intervalValue).toPrecision()
      const calcMinValue = +bigValue.minus(intervalValue).toPrecision()
      return {
        max: isNumber(max) ? Math.min(max, calcMaxValue) : calcMaxValue,
        min: isNumber(min) ? Math.max(min, calcMinValue) : calcMinValue,
        step: +stepValue.toPrecision(),
      }
    }
    return {}
  }

  /**
   * 获取动态组件类型
   */
  private getCompType(item: IParamItem): string {
    const result = 'a-input'
    const mapping: any = {
      number: 'a-input-number',
      checkbox: 'a-checkbox-group',
      select: 'a-select',
      string: 'a-input',
      int: 'a-input-number',
      slider: 'a-slide',
    }
    if (mapping[item.type]) {
      return mapping[item.type]
    }
    return result
  }
}
</script>

<style lang="less" scoped>
.operator-configuration {
  height: 100%;
  overflow-y: auto;
  padding: 20px;

  &::-webkit-scrollbar {
    visibility: hidden;
    width: 6px;
  }

  &::-webkit-scrollbar-thumb {
    background: rgba(144, 147, 153, 0.5);
    border-radius: 6px;
    visibility: hidden;
  }

  &:hover {
    &::-webkit-scrollbar {
      visibility: visible;
    }

    &::-webkit-scrollbar-thumb {
      visibility: visible;
    }
  }

  &::-webkit-scrollbar-track {
    background: transparent;
    border-radius: 5px;
  }

  /deep/ .ant-form-item {
    margin-bottom: 0;
  }

  /deep/ .ant-input-number {
    width: 100%;
  }

  /deep/ .ant-form-item-label > label {
    color: var(--controller-label) !important;
  }

  /deep/ .ant-checkbox,
  /deep/ .ant-checkbox-wrapper,
  /deep/ .ant-radio,
  /deep/ .ant-radio-wrapper {
    color: var(--controller-label);
  }

  /deep/ .ant-input,
  /deep/ .ant-select-selection,
  /deep/ .ant-input-number,
  /deep/ .ant-input-number-handler-wrap {
    background-color: transparent;
    border: 1px solid var(--controller-input-border);
    color: var(--controller-label);

    &:hover,
    &:focus {
      border: 1px solid #6973ff;
      border-radius: 2px;
      outline: none;
    }

    &.ant-input-number-disabled {
      opacity: 0.6;
    }
  }

  /deep/ .ant-input-number-handler-up-inner,
  /deep/ .ant-input-number-handler-down-inner {
    color: var(--controller-innput-arrow);
  }

  /deep/ .ant-slider-rail {
    background-color: var(--controller-slider-rail);
  }

  /deep/ .ant-slider-track {
    background-color: #6973ff;
  }

  /deep/ .ant-select-arrow,
  /deep/ .ant-checkbox-disabled + span {
    color: var(--controller-label);
  }

  /deep/ .form-select,
  /deep/ .form-radio-group {
    background-color: var(--checkbox-group);
  }
}

.operator-configuration.remove-scroll {
  overflow: hidden;
}
</style>
<style lang="less">
.operator-configuration-dropdown {
  background-color: var(--component-bg-color);
  color: var(--controller-label);

  .ant-select-dropdown-menu-item {
    color: var(--controller-label);
  }

  .ant-select-dropdown-menu-item-selected {
    background-color: var(--table-row-hover);
  }

  .ant-select-dropdown-menu-item-active:not(.ant-select-dropdown-menu-item-disabled) {
    background-color: var(--table-row-hover);
  }
}
</style>
